﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using AEA.RSSFeedReaderLib;
using Forms = System.Windows.Forms;

namespace AEA.RSSFeedReader
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class MainApplication : Window
    {
        RSSFeed _handleFeeds;
        AddFeedUc AddFeedControl = null;

        /// <summary>
        /// Initialize a new instance of the MainApplication class.
        /// </summary>
        public MainApplication()
        {
            this.InitializeComponent();

            _handleFeeds = new RSSFeed();
            _handleFeeds.Load();
            _handleFeeds.CleanFeedItems(Properties.Resources.ReloadingFeeds);
            _handleFeeds.DownLoadFeedCompleted += new RSSFeed.DownLoadFeedCompletedHandler(DownLoadFeedCompleted);
            _handleFeeds.DownLoadItemFeedCompleted += new RSSFeed.DownLoadItemFeedCompletedHandler(DownLoadItemFeedCompleted);

            this.Closed += new EventHandler(MainApplicationClosed);
            this.Feeds.ItemsSource = null;

            if (_handleFeeds.Channels.Count > 0)
            {
                ReloadLoadFeeds(_handleFeeds.Channels);
            }
        }

        #region Private Methods
        /// <summary>
        /// Kicks off the process to start downloading the feeds.
        /// </summary>
        /// <param name="feedChannel"></param>
        private void GetFeedItems(string feedChannel)
        {
            if (!string.IsNullOrEmpty(feedChannel))
                _handleFeeds.DownLoadFeed(RSSFeed.ConvertToUri(feedChannel));
        }

        /// <summary>
        /// Reloads the feeds.
        /// </summary>
        /// <param name="channelFeedCollection"></param>
        private void ReloadLoadFeeds(ChannelFeedCollection channelFeedCollection)
        {
            foreach (ChannelFeed channelFeed in channelFeedCollection)
            {
                StartReloadChannelFeedItems(channelFeed);
            }
        }

        /// <summary>
        /// Gets the requested ChannelFeed.
        /// </summary>
        /// <param name="channelFeedToRetieve">The ChannelFeed object to return.</param>
        /// <returns>The selected ChannelFeed.</returns>
        private ChannelFeed GetChannelFeedSelected(ChannelFeed channelFeedToRetieve)
        {
            return Feeds.Items.GetItemAt(Feeds.Items.IndexOf(channelFeedToRetieve)) as ChannelFeed;
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Event handler for when the application is closed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainApplicationClosed(object sender, EventArgs e)
        {
            _handleFeeds.Save();
        }

        /// <summary>
        /// Event handler for when the ChannelFeeds have been downloaded
        /// </summary>
        /// <param name="e"></param>
        private void DownLoadFeedCompleted(DownLoadFeedCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if (Feeds.ItemsSource == null)
                {
                    Feeds.ItemsSource = e.Channels;
                }
            }
            else
            {
                string msg = string.Format(Properties.Resources.AddChannelError, e.Error.Message);

                if (e.Error.InnerException != null)
                    msg += "\n\n" + e.Error.InnerException.Message;

               Forms.MessageBox.Show(msg,
                        this.Title, Forms.MessageBoxButtons.OK,
                            Forms.MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Event handler for when the ItemFeeds of a ChannelFeed have been reloaded.
        /// </summary>
        /// <param name="e"></param>
        private void DownLoadItemFeedCompleted(DownLoadItemFeedCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                if (Feeds.ItemsSource == null)
                {
                    Feeds.ItemsSource = _handleFeeds.Channels;
                }

                int channelIndex = Feeds.Items.IndexOf(e.Channel);
                (Feeds.Items[channelIndex] as ChannelFeed).ItemFeeds = e.ItemFeeds;
            }
            else
            {
                string msg = string.Format(Properties.Resources.ReloadItemFeedsError, e.ChannelUri);

                if (e.Error.InnerException != null)
                    msg += "\n\n" + e.Error.InnerException.Message;

                Forms.MessageBox.Show(msg,
                        this.Title, Forms.MessageBoxButtons.OK,
                            Forms.MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Navigates to the ItemFeed link
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NavigateToItemFeed(object sender, MouseButtonEventArgs e)
        {
            TextBlock feed = sender as TextBlock;
            FeedWebBrowser.Navigate(RSSFeed.ConvertToUri((feed.Tag as ItemFeed).Link));
        }

        /// <summary>
        /// Copies the link of the ItemFeed to the Clipboard.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CopyItemFeedLink(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            Clipboard.SetText((menuItem.Tag as ItemFeed).Link.ToString());
        }

        /// <summary>
        /// Opens the website for the feed in the default web browser.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void VisitWebsite(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            System.Diagnostics.Process.Start((menuItem.Tag as ChannelFeed).ChannelLink.ToString());
        }

        /// <summary>
        /// Reloads the ItemFeeds for a ChannelFeed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ReloadChannelFeedItems(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            ChannelFeed channelToreload = GetChannelFeedSelected(menuItem.Tag as ChannelFeed);

            StartReloadChannelFeedItems(channelToreload);
        }

        /// <summary>
        /// Begins reloading the item feeds for the specified ChannelFeed.
        /// </summary>
        /// <param name="channelToreload">ChannelFeed to reload items for.</param>
        private void StartReloadChannelFeedItems(ChannelFeed channelToreload)
        {
            channelToreload.ItemFeeds.Insert(0, new ItemFeed(Properties.Resources.ReloadingFeeds, null, null));
            _handleFeeds.DownLoadChannelItemFeeds(channelToreload);
        }

        /// <summary>
        /// Deletes the selected feed from the ChannelFeeds.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DeleteChannelFeed(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            ChannelFeed channelToDelete = GetChannelFeedSelected(menuItem.Tag as ChannelFeed);

            if (Forms.MessageBox.Show(string.Format(string.Format(Properties.Resources.ConfirmDelete, channelToDelete.ChannelTitle)),
                this.Title,
                Forms.MessageBoxButtons.YesNo,
                Forms.MessageBoxIcon.Question)
                == Forms.DialogResult.Yes)
            {
                _handleFeeds.Channels.Remove(channelToDelete);
            }
        }
        #endregion

        #region Commands
        /// <summary>
        /// Add a new feed to the list.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoNewCommand(object sender, ExecutedRoutedEventArgs e)
        {
            AddFeedControl = new AddFeedUc();
            AddFeedControl.Owner = this;
            AddFeedControl.WindowStartupLocation = WindowStartupLocation.CenterOwner;
            AddFeedControl.Icon = this.Icon;
            AddFeedControl.Title = Properties.Resources.AddRSSFeedTitle;

            if (AddFeedControl.ShowDialog() == true)
            {
                if (!_handleFeeds.IsChannelFeedInCollection(AddFeedControl.InputText))
                    GetFeedItems(AddFeedControl.InputText);
            }
        }

        /// <summary>
        /// Imports the feeds from a settings file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoImportSettingsCommand(object sender, ExecutedRoutedEventArgs e)
        {
            Forms.OpenFileDialog ofd = new Forms.OpenFileDialog();
            ofd.Filter = Properties.Resources.XmlFiles + "|" + Properties.Resources.XmlExtension;
            ofd.Title = Properties.Resources.ImportSettingsDialogTitle;

            if (ofd.ShowDialog() == Forms.DialogResult.OK)
            {
                try
                {
                    List<string> feedUris = ImportExportSettings.Import(ofd.FileName);

                    if (feedUris.Count > 0 || feedUris != null)
                    {
                        foreach (string s in feedUris)
                        {
                            if (!_handleFeeds.IsChannelFeedInCollection(s))
                            {
                                GetFeedItems(s);
                            }
                        }
                    }
                }
                catch (ImportExportException ex)
                {
                    string msg = string.Format(Properties.Resources.ImportSettingsError, ex.Message);
                    if (ex.InnerException != null)
                        msg += "\n\n" + ex.InnerException.Message;

                    Forms.MessageBox.Show(msg,
                        this.Title, Forms.MessageBoxButtons.OK,
                       Forms.MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// Export settings to xml file.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoExportSettingsCommand(object sender, ExecutedRoutedEventArgs e)
        {
            Forms.SaveFileDialog sfd = new Forms.SaveFileDialog();
            sfd.Filter = Properties.Resources.XmlFiles + "|" + Properties.Resources.XmlExtension;
            sfd.Title = Properties.Resources.ExportSettingsDialogTitle;
            sfd.FileName = Properties.Resources.ExportSettingsDefaultFileName;

            if (sfd.ShowDialog() == Forms.DialogResult.OK)
            {
                try
                {
                    if (ImportExportSettings.Export(sfd.FileName, _handleFeeds))
                    {
                        Forms.MessageBox.Show(Properties.Resources.ExportSettingsSuccessful,
                            this.Title, Forms.MessageBoxButtons.OK,
                            Forms.MessageBoxIcon.Information);
                    }
                }
                catch (ImportExportException ex)
                {
                    string msg = string.Format(Properties.Resources.ExportSettingsError, ex.Message);
                    if (ex.InnerException != null)
                        msg += "\n\n" + ex.InnerException.Message;

                    Forms.MessageBox.Show(msg,
                        this.Title, Forms.MessageBoxButtons.OK,
                        Forms.MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// Determines if the ExportSettingsCommand can be executed or not.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CanExecuteExportSettingsCommand(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Feeds.HasItems;
        }

        /// <summary>
        /// Clears the ChannFeeds from the list of feeds.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoDeleteAllChannelFeeds(object sender, ExecutedRoutedEventArgs e)
        {
            if (Forms.MessageBox.Show(Properties.Resources.ConfirmDeleteAllChannelFeeds,
                this.Title,
                Forms.MessageBoxButtons.YesNo,
                Forms.MessageBoxIcon.Question)
                == Forms.DialogResult.Yes)
            {
                _handleFeeds.Channels.Clear();
            }
        }

        /// <summary>
        /// Determines if the DeleteAllChannelFeedsCommand can be executed or not.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CanExecuteDeleteAllChannelFeeds(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Feeds.HasItems;
        }

        /// <summary>
        /// Exit the application.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoExitCommand(object sender, ExecutedRoutedEventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Reload all the ItemFeeds.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DoReloadAllItemFeeds(object sender, ExecutedRoutedEventArgs e)
        {
            foreach (ChannelFeed channelFeed in _handleFeeds.Channels)
            {
                StartReloadChannelFeedItems(channelFeed);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CanExecuteReloadAllItemFeeds(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Feeds.HasItems;
        }
        #endregion
    }
}